package com.ruoyi.project.system.controller;

import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.security.service.TokenService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.domain.*;
import com.ruoyi.project.system.service.IReminderRulesService;
import com.ruoyi.project.system.service.ITaskRecipientsService;
import com.ruoyi.project.system.service.ITasksService;
import com.ruoyi.project.system.service.ITaskPushService;
import com.ruoyi.project.system.service.ISysUserService;
import com.ruoyi.project.system.service.IReminderLogsService;
import com.ruoyi.project.system.service.IContentService;
import com.ruoyi.project.system.service.INotificationService;
import com.ruoyi.project.system.service.IUserNotificationService;
import com.ruoyi.project.system.service.IUserTaskCompletionService;
import com.ruoyi.project.system.mapper.ContentAttachmentMapper;
import com.ruoyi.project.system.mapper.ContentContactMapper;
import com.ruoyi.project.system.mapper.ContentCategoryMapper;
import com.ruoyi.project.system.mapper.UserTaskCompletionMapper;
import com.ruoyi.project.system.mapper.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.ruoyi.project.system.domain.SysSnapshot;
import com.ruoyi.project.system.service.ISysSnapshotService;
import org.springframework.web.multipart.MultipartFile;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.project.system.mapper.SysSnapshotImageMapper;
import com.ruoyi.project.system.domain.SysSnapshotImage;
import com.ruoyi.project.system.mapper.ReminderLogsMapper;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.LinkedHashMap;
import java.lang.reflect.Field;
import com.ruoyi.project.system.utils.ObjectToMapUtils;
import com.ruoyi.project.monitor.service.ISysJobService;
import com.ruoyi.project.monitor.domain.SysJob;
import com.ruoyi.project.system.domain.CarApply;
import com.ruoyi.project.system.mapper.CarApplyMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

/**
 * AppController
 * 
 * @author ruoyi
 * @date 2025-06-16
 */
@Controller
@RequestMapping("/system/app")
public class AppController {
    @Autowired
    private ITasksService tasksService;

    @Autowired
    private ITaskRecipientsService taskRecipientsService;

    @Autowired
    private IReminderRulesService reminderRulesService;

    @Autowired
    private ITaskPushService taskPushService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private IReminderLogsService reminderLogsService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private ReminderLogsMapper reminderLogsMapper;

    @Autowired
    private IContentService contentService;

    @Autowired
    private ContentAttachmentMapper contentAttachmentMapper;

    @Autowired
    private ContentContactMapper contentContactMapper;

    @Autowired
    private ContentCategoryMapper contentCategoryMapper;

    @Autowired
    private INotificationService notificationService;

    @Autowired
    private IUserNotificationService userNotificationService;

    @Autowired
    private ISysSnapshotService sysSnapshotService;

    @Autowired
    private SysSnapshotImageMapper sysSnapshotImageMapper;

    @Autowired
    private UserTaskCompletionMapper userTaskCompletionMapper;
    @Autowired
    private IUserTaskCompletionService userTaskCompletionService;

    @Autowired
    private TaskCycleDeadlinesMapper taskCycleDeadlinesMapper;

    @Autowired
    private ISysJobService sysJobService;

    @Autowired
    private CarApplyMapper carApplyMapper;

    /**
     * 更新用户推送设备ID
     */
    @PostMapping("/registerDevice")
    @ResponseBody
    public AjaxResult updateDeviceId(@RequestBody Tydto deviceDto) {
        try {
            // 获取当前登录用户ID
            Long userId = SecurityUtils.getUserId();

            // 获取用户信息
            SysUser user = userService.selectUserById(userId);
            if (user == null) {
                return AjaxResult.error("用户不存在");
            }

            // 验证设备ID是否为空
            if (deviceDto.getDeviceId() == null || deviceDto.getDeviceId().trim().isEmpty()) {
                return AjaxResult.error("设备ID不能为空");
            }

            // 更新用户的remark字段为设备ID
            user.setRemark(deviceDto.getDeviceId().trim());
            user.setUpdateBy(SecurityUtils.getUsername());
            user.setUpdateTime(new Date());

            int result = userService.updateUserRemark(user);
            if (result > 0) {
                return AjaxResult.success("设备ID更新成功");
            } else {
                return AjaxResult.error("设备ID更新失败");
            }

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("更新设备ID失败：" + e.getMessage());
        }
    }

    /**
     * 创建任务接口（包含接收人和提醒规则）
     */
    @PostMapping("/createTask")
    @ResponseBody
    @Transactional
    public AjaxResult createTask(@RequestBody Tydto dto) {
        try {
            // 1. 创建任务基本信息
            Tasks task = new Tasks();
            task.setTitle(dto.getTitle());
            task.setDescription(dto.getDescription());
            task.setTaskType(dto.getTaskType());
            task.setPriority(dto.getPriority());
            task.setCreatorId(SecurityUtils.getUserId());
            task.setDeptId(SecurityUtils.getDeptId());
            task.setStatus("进行中");
            task.setIsActive(1); // 激活状态
            task.setCreatedAt(new Date());
            task.setUpdatedAt(new Date());

            // 设置生效时间
            if (dto.getEffectiveStart() != null && !dto.getEffectiveStart().isEmpty()) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                task.setEffectiveStart(dateFormat.parse(dto.getEffectiveStart()));
            }
            if (dto.getEffectiveEnd() != null && !dto.getEffectiveEnd().isEmpty()) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                task.setEffectiveEnd(dateFormat.parse(dto.getEffectiveEnd()));
            }

            // 插入任务并获取生成的ID
            int taskResult = tasksService.insertTasks(task);
            if (taskResult <= 0) {
                return AjaxResult.error("创建任务失败");
            }

            // 获取刚插入的任务ID
            Long taskId = task.getId();

            // 2. 设置任务接收人
            if (dto.getRecipientIds() != null && dto.getRecipientIds().length > 0) {
                for (Long recipientId : dto.getRecipientIds()) {
                    TaskRecipients recipient = new TaskRecipients();
                    recipient.setTaskId(taskId);
                    recipient.setUserId(recipientId);
                    taskRecipientsService.insertTaskRecipients(recipient);
                }
            }

            // 3. 设置提醒规则
            ReminderRules reminderRule = new ReminderRules();
            reminderRule.setTaskId(taskId);
            reminderRule.setFrequency(dto.getFrequency());

            // 解析时间（格式：HH:mm）
            if ("immediate".equals(dto.getFrequency())) {
                // 如果是立即提醒，使用当前时间
                reminderRule.setTimeOfDay(new Date());
            } else if ("once".equals(dto.getFrequency())) {
                // 如果是一次性提醒，使用指定的完整时间
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date specifiedTime = dateFormat.parse(dto.getTimeOfDay());
                reminderRule.setTimeOfDay(specifiedTime);
            } else {
                // 其他频率类型，解析前端传来的时间
                SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                Date time = timeFormat.parse(dto.getTimeOfDay());
                reminderRule.setTimeOfDay(time);
            }

            // 根据频率设置相应的规则参数
            switch (dto.getFrequency()) {
                case "immediate":
                    // 立即推送类型，无需设置额外参数
                    break;
                case "once":
                    // 一次性推送类型，无需设置额外参数
                    break;
                case "daily":
                    // 每日提醒：如果今天的时间已过，设为明天
                    if (reminderRule.getTimeOfDay() != null) {
                        Calendar timeCalendar = Calendar.getInstance();
                        timeCalendar.setTime(reminderRule.getTimeOfDay());
                        if (timeCalendar.before(Calendar.getInstance())) {
                            timeCalendar.add(Calendar.DAY_OF_YEAR, 1);
                        }
                        reminderRule.setTimeOfDay(timeCalendar.getTime());
                    }
                    break;
                case "weekly":
                    if (dto.getWeeklyDays() != null && !dto.getWeeklyDays().isEmpty()) {
                        reminderRule.setWeeklyDays(dto.getWeeklyDays());
                        reminderRule.setCycleDeadlineWeekDay(dto.getCycleDeadlineWeekDay());
                    }
                    break;
                case "monthly":
                    if (dto.getMonthlyDays() != null && !dto.getMonthlyDays().isEmpty()) {
                        reminderRule.setMonthlyDays(dto.getMonthlyDays());
                        reminderRule.setCycleDeadlineMonthDay(dto.getCycleDeadlineMonthDay());
                    }
                    break;
                case "yearly":
                    if (dto.getYearlyMonths() != null && !dto.getYearlyMonths().isEmpty()) {
                        reminderRule.setYearlyMonths(dto.getYearlyMonths());
                        reminderRule.setCycleDeadlineYearMonth(dto.getCycleDeadlineYearMonth());
                    }
                    if (dto.getYearlyDays() != null && !dto.getYearlyDays().isEmpty()) {
                        reminderRule.setYearlyDays(dto.getYearlyDays());
                        reminderRule.setCycleDeadlineYearDay(dto.getCycleDeadlineYearDay());
                    }
                    break;
                // case "custom":
                // if (dto.getCustomRule() != null && !dto.getCustomRule().isEmpty()) {
                // reminderRule.setCustomRule(dto.getCustomRule());
                // }
                // break;
            }

            // 计算下次提醒时间
            Date nextTrigger = calculateNextTrigger(reminderRule);
            reminderRule.setNextTrigger(nextTrigger);
            reminderRule.setCreatedAt(new Date());
            reminderRule.setUpdatedAt(new Date());

            int ruleResult = reminderRulesService.insertReminderRules(reminderRule);
            if (ruleResult <= 0) {
                return AjaxResult.error("创建提醒规则失败");
            }

            // 4. 创建第一个任务周期截止时间
            TaskCycleDeadlines cycleDeadline = new TaskCycleDeadlines();
            cycleDeadline.setTaskId(taskId);
            cycleDeadline.setCycleType(dto.getFrequency());
            cycleDeadline.setCycleStart(task.getEffectiveStart() != null ? task.getEffectiveStart() : new Date());

            // 根据频率类型处理周期截止时间
            if ("once".equals(dto.getFrequency()) || "immediate".equals(dto.getFrequency())) {
                // 一次性类型：使用完整的日期时间
                if (dto.getCycleDeadline() != null && !dto.getCycleDeadline().isEmpty()) {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    cycleDeadline.setDeadline(dateFormat.parse(dto.getCycleDeadline()));
                }
            } else if ("daily".equals(dto.getFrequency())) {
                // 每天类型：前端只传时间（HH:mm），需补全为今天的日期时间
                if (dto.getCycleDeadline() != null && !dto.getCycleDeadline().isEmpty()) {
                    try {
                        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                        Date timeOnly = timeFormat.parse(dto.getCycleDeadline());
                        Calendar now = Calendar.getInstance();
                        Calendar deadlineCalendar = Calendar.getInstance();
                        deadlineCalendar.setTime(timeOnly);
                        deadlineCalendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
                        deadlineCalendar.set(Calendar.MONTH, now.get(Calendar.MONTH));
                        deadlineCalendar.set(Calendar.DAY_OF_MONTH, now.get(Calendar.DAY_OF_MONTH));
                        deadlineCalendar.set(Calendar.SECOND, 0);
                        deadlineCalendar.set(Calendar.MILLISECOND, 0);
                        if (deadlineCalendar.before(now)) {
                            deadlineCalendar.add(Calendar.DAY_OF_YEAR, 1);
                        }
                        cycleDeadline.setDeadline(deadlineCalendar.getTime());
                    } catch (Exception e) {
                        return AjaxResult.error("时间格式错误，请使用HH:mm格式");
                    }
                }
            } else if ("weekly".equals(dto.getFrequency())) {
                // 每周类型：前端只传时间（HH:mm）和星期几，需补全为本周的日期时间
                if (dto.getCycleDeadlineWeekDay() != null && dto.getCycleDeadline() != null
                        && !dto.getCycleDeadline().isEmpty()) {
                    try {
                        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                        Date timeOnly = timeFormat.parse(dto.getCycleDeadline());
                        Calendar now = Calendar.getInstance();
                        Calendar deadlineCalendar = Calendar.getInstance();
                        deadlineCalendar.setTime(timeOnly);
                        deadlineCalendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
                        deadlineCalendar.set(Calendar.WEEK_OF_YEAR, now.get(Calendar.WEEK_OF_YEAR));
                        deadlineCalendar.set(Calendar.DAY_OF_WEEK, dto.getCycleDeadlineWeekDay());
                        deadlineCalendar.set(Calendar.SECOND, 0);
                        deadlineCalendar.set(Calendar.MILLISECOND, 0);
                        if (deadlineCalendar.before(now)) {
                            deadlineCalendar.add(Calendar.WEEK_OF_YEAR, 1);
                        }
                        cycleDeadline.setDeadline(deadlineCalendar.getTime());
                    } catch (Exception e) {
                        return AjaxResult.error("时间格式错误，请使用HH:mm格式");
                    }
                }
            } else if ("monthly".equals(dto.getFrequency())) {
                // 每月类型：前端只传时间（HH:mm）和几号，需补全为本月的日期时间
                if (dto.getCycleDeadlineMonthDay() != null && dto.getCycleDeadline() != null
                        && !dto.getCycleDeadline().isEmpty()) {
                    try {
                        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                        Date timeOnly = timeFormat.parse(dto.getCycleDeadline());
                        Calendar now = Calendar.getInstance();
                        Calendar deadlineCalendar = Calendar.getInstance();
                        deadlineCalendar.setTime(timeOnly);
                        deadlineCalendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
                        deadlineCalendar.set(Calendar.MONTH, now.get(Calendar.MONTH));
                        deadlineCalendar.set(Calendar.DAY_OF_MONTH, dto.getCycleDeadlineMonthDay());
                        deadlineCalendar.set(Calendar.SECOND, 0);
                        deadlineCalendar.set(Calendar.MILLISECOND, 0);
                        if (deadlineCalendar.before(now)) {
                            deadlineCalendar.add(Calendar.MONTH, 1);
                        }
                        cycleDeadline.setDeadline(deadlineCalendar.getTime());
                    } catch (Exception e) {
                        return AjaxResult.error("时间格式错误，请使用HH:mm格式");
                    }
                }
            } else if ("yearly".equals(dto.getFrequency())) {
                // 每年类型：前端只传时间（HH:mm）、月份、几号，需补全为今年的日期时间
                if (dto.getCycleDeadlineYearMonth() != null && dto.getCycleDeadlineYearDay() != null
                        && dto.getCycleDeadline() != null && !dto.getCycleDeadline().isEmpty()) {
                    try {
                        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                        Date timeOnly = timeFormat.parse(dto.getCycleDeadline());
                        Calendar now = Calendar.getInstance();
                        Calendar deadlineCalendar = Calendar.getInstance();
                        deadlineCalendar.setTime(timeOnly);
                        deadlineCalendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
                        deadlineCalendar.set(Calendar.MONTH, dto.getCycleDeadlineYearMonth() - 1); // Calendar.MONTH从0开始
                        deadlineCalendar.set(Calendar.DAY_OF_MONTH, dto.getCycleDeadlineYearDay());
                        deadlineCalendar.set(Calendar.SECOND, 0);
                        deadlineCalendar.set(Calendar.MILLISECOND, 0);
                        if (deadlineCalendar.before(now)) {
                            deadlineCalendar.add(Calendar.YEAR, 1);
                        }
                        cycleDeadline.setDeadline(deadlineCalendar.getTime());
                    } catch (Exception e) {
                        return AjaxResult.error("时间格式错误，请使用HH:mm格式");
                    }
                }
            } else if ("custom".equals(dto.getFrequency())) {
                // 自定义类型：前端只传时间（HH:mm），需补全为今天的日期时间
                if (dto.getCycleDeadline() != null && !dto.getCycleDeadline().isEmpty()) {
                    try {
                        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                        Date timeOnly = timeFormat.parse(dto.getCycleDeadline());
                        Calendar now = Calendar.getInstance();
                        Calendar deadlineCalendar = Calendar.getInstance();
                        deadlineCalendar.setTime(timeOnly);
                        deadlineCalendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
                        deadlineCalendar.set(Calendar.MONTH, now.get(Calendar.MONTH));
                        deadlineCalendar.set(Calendar.DAY_OF_MONTH, now.get(Calendar.DAY_OF_MONTH));
                        deadlineCalendar.set(Calendar.SECOND, 0);
                        deadlineCalendar.set(Calendar.MILLISECOND, 0);
                        if (deadlineCalendar.before(now)) {
                            deadlineCalendar.add(Calendar.DAY_OF_YEAR, 1);
                        }
                        cycleDeadline.setDeadline(deadlineCalendar.getTime());
                    } catch (Exception e) {
                        return AjaxResult.error("时间格式错误，请使用HH:mm格式");
                    }
                }
            }

            cycleDeadline.setIsCurrent(1); // 设置为当前周期
            cycleDeadline.setCreatedAt(new Date());
            cycleDeadline.setUpdatedAt(new Date());

            // 当前周期的开始时间
            Date cycleStart = cycleDeadline.getCycleStart(); // 这个应该是本周期的起点
            Calendar nextCycleEnd = Calendar.getInstance();
            nextCycleEnd.setTime(cycleStart);

            if ("once".equals(dto.getFrequency()) || "immediate".equals(dto.getFrequency())) {
                cycleDeadline.setCycleEnd(
                        task.getEffectiveEnd() != null ? task.getEffectiveEnd() : cycleDeadline.getDeadline());
            } else {
                switch (dto.getFrequency()) {
                    case "daily":
                        nextCycleEnd.add(Calendar.DAY_OF_YEAR, 1);
                        break;
                    case "weekly":
                        nextCycleEnd.add(Calendar.WEEK_OF_YEAR, 1);
                        break;
                    case "monthly":
                        nextCycleEnd.add(Calendar.MONTH, 1);
                        break;
                    case "yearly":
                        nextCycleEnd.add(Calendar.YEAR, 1);
                        break;
                }
                cycleDeadline.setCycleEnd(nextCycleEnd.getTime());
            }
            if (!"once".equals(dto.getFrequency()) && !"immediate".equals(dto.getFrequency())) {
                cycleDeadline.setNextTrigger(nextCycleEnd.getTime());
                // 预约下一个任务周期的创建
                scheduleNextCycle(taskId, cycleDeadline.getNextTrigger(), cycleDeadline.getDeadline());
            }
            int cycleResult = taskCycleDeadlinesMapper.insert(cycleDeadline);
            if (cycleResult <= 0) {
                return AjaxResult.error("创建任务周期失败");
            }

            // 5. 为每个任务接收人创建用户任务完成状态记录
            if (dto.getRecipientIds() != null && dto.getRecipientIds().length > 0) {
                for (Long recipientId : dto.getRecipientIds()) {
                    UserTaskCompletion userCompletion = new UserTaskCompletion();
                    userCompletion.setTaskId(taskId.intValue());
                    userCompletion.setUserId(recipientId);
                    userCompletion.setCycleId(cycleDeadline.getId());
                    userCompletion.setStatus("进行中");
                    userCompletion.setCreatedAt(new Date());
                    userCompletion.setUpdatedAt(new Date());

                    int completionResult = userTaskCompletionMapper.insert(userCompletion);
                    if (completionResult <= 0) {
                        return AjaxResult.error("创建用户任务完成状态失败");
                    }
                }
            }

            // 6. 推送任务创建通知给接收人（仅在频率为"immediate"时立即推送）
            if ("immediate".equals(dto.getFrequency())) {
                // 检查任务是否在有效期内
                if (isTaskValid(task)) {
                    return AjaxResult.success("任务创建成功，任务ID：" + taskId + "，将由系统立即推送通知");
                } else {
                    return AjaxResult.success("任务创建成功，任务ID：" + taskId + "，但任务不在有效期内，未推送通知");
                }
            } else {
                // 非立即推送类型，任务创建成功，等待定时任务触发
                return AjaxResult.success("任务创建成功，任务ID：" + taskId + "，下次提醒时间：" +
                        new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(nextTrigger) + "，将在指定时间推送通知");
            }

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("创建任务失败：" + e.getMessage());
        }
    }

    /**
     * 预约下一个任务周期的创建
     * 
     * @param taskId         任务ID
     * @param nextCycleStart 下周期开始时间
     * @param frequency      周期类型
     */
    private void scheduleNextCycle(Long taskId, Date nextCycleStart, Date nextCycleEnd) {
        try {
            // 检查任务是否在有效期内
            Tasks task = tasksService.selectTasksById(taskId);
            if (task == null) {
                return;
            }
            // 检查任务是否激活
            if (task.getIsActive() == null || task.getIsActive() != 1) {
                return;
            }
            // 检查任务生效结束时间（为空表示永久有效）
            if (task.getEffectiveEnd() != null) {
                // 如果下个周期的开始时间已超过任务有效期，不预约
                if (nextCycleStart.after(task.getEffectiveEnd())) {
                    return;
                }
                // 如果下个周期的结束时间超过任务有效期，不预约
                if (nextCycleEnd.after(task.getEffectiveEnd())) {
                    return;
                }
            }
            // 生成 cron 表达式（这里只处理到日期级别，复杂周期可扩展）
            String cron = dateToCron(nextCycleStart);
            SysJob job = new SysJob();
            job.setJobName("CreateNextCycleJob_" + taskId);
            job.setJobGroup("TaskCycle");
            job.setInvokeTarget("createNextCycleJob.execute(" + taskId + ")");
            job.setCronExpression(cron);
            job.setMisfirePolicy("1");
            job.setConcurrent("0");
            job.setStatus("0");
            job.setRemark("任务ID: " + taskId + " 的下周期创建");
            // 获取 ISysJobService 实例（建议通过成员变量注入）
            sysJobService.insertJob(job);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将 Date 转换为 cron 表达式（精确到分钟）
     */
    private String dateToCron(Date date) {
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        calendar.setTime(date);
        int second = calendar.get(java.util.Calendar.SECOND);
        int minute = calendar.get(java.util.Calendar.MINUTE);
        int hour = calendar.get(java.util.Calendar.HOUR_OF_DAY);
        int day = calendar.get(java.util.Calendar.DAY_OF_MONTH);
        int month = calendar.get(java.util.Calendar.MONTH) + 1;
        int year = calendar.get(java.util.Calendar.YEAR);
        // 格式：秒 分 时 日 月 星期 年
        return String.format("%d %d %d %d %d ? %d", second, minute, hour, day, month, year);
    }

    /**
     * 更新任务
     */
    @PostMapping("/updateTask")
    @ResponseBody
    @Transactional
    public AjaxResult updateTask(@RequestBody Tydto dto) {
        try {
            // 验证任务ID
            if (dto.getTaskId() == null) {
                return AjaxResult.error("任务ID不能为空");
            }

            // 获取任务信息
            Tasks task = tasksService.selectTasksById(dto.getTaskId());
            if (task == null) {
                return AjaxResult.error("任务不存在");
            }

            // 更新任务基本信息
            task.setTitle(dto.getTitle());
            task.setDescription(dto.getDescription());
            task.setTaskType(dto.getTaskType());
            task.setPriority(dto.getPriority());
            task.setDeadline(dto.getDeadline());
            task.setUpdateBy(SecurityUtils.getUsername());
            task.setUpdatedAt(new Date());

            // 设置生效时间
            if (dto.getEffectiveStart() != null && !dto.getEffectiveStart().isEmpty()) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                task.setEffectiveStart(dateFormat.parse(dto.getEffectiveStart()));
            }
            if (dto.getEffectiveEnd() != null && !dto.getEffectiveEnd().isEmpty()) {
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                task.setEffectiveEnd(dateFormat.parse(dto.getEffectiveEnd()));
            }

            // 更新任务
            int taskResult = tasksService.updateTasks(task);
            if (taskResult <= 0) {
                return AjaxResult.error("更新任务失败");
            }

            // 更新任务接收人
            if (dto.getRecipientIds() != null && dto.getRecipientIds().length > 0) {
                // 先删除原有的接收人
                taskRecipientsService.deleteTaskRecipientsByTaskId(task.getId());

                // 添加新的接收人
                for (Long recipientId : dto.getRecipientIds()) {
                    TaskRecipients recipient = new TaskRecipients();
                    recipient.setTaskId(task.getId());
                    recipient.setUserId(recipientId);
                    taskRecipientsService.insertTaskRecipients(recipient);
                }
            }

            // 更新提醒规则
            ReminderRules reminderRule = reminderRulesService.selectReminderRulesByTaskId(task.getId());
            if (reminderRule != null) {
                reminderRule.setFrequency(dto.getFrequency());

                // 解析时间（格式：HH:mm）
                if ("immediate".equals(dto.getFrequency())) {
                    // 如果是立即提醒，使用当前时间
                    reminderRule.setTimeOfDay(new Date());
                } else if ("once".equals(dto.getFrequency())) {
                    // 如果是一次性提醒，使用指定的完整时间
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date specifiedTime = dateFormat.parse(dto.getTimeOfDay());
                    reminderRule.setTimeOfDay(specifiedTime);
                } else {
                    // 其他频率类型，前端只传时间（HH:mm），需补全为今天的日期时间
                    try {
                        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                        Date timeOnly = timeFormat.parse(dto.getTimeOfDay());
                        Calendar now = Calendar.getInstance();
                        Calendar timeCalendar = Calendar.getInstance();
                        timeCalendar.setTime(timeOnly);
                        timeCalendar.set(Calendar.YEAR, now.get(Calendar.YEAR));
                        timeCalendar.set(Calendar.MONTH, now.get(Calendar.MONTH));
                        timeCalendar.set(Calendar.DAY_OF_MONTH, now.get(Calendar.DAY_OF_MONTH));
                        timeCalendar.set(Calendar.SECOND, 0);
                        timeCalendar.set(Calendar.MILLISECOND, 0);
                        // 如果今天的时间已过，设为明天
                        if (timeCalendar.before(now)) {
                            timeCalendar.add(Calendar.DAY_OF_YEAR, 1);
                        }
                        reminderRule.setTimeOfDay(timeCalendar.getTime());
                    } catch (Exception e) {
                        return AjaxResult.error("时间格式错误，请使用HH:mm格式");
                    }
                }

                // 根据频率设置相应的规则参数
                switch (dto.getFrequency()) {
                    case "immediate":
                        // 立即推送类型，无需设置额外参数
                        break;
                    case "once":
                        // 一次性推送类型，无需设置额外参数
                        break;
                    case "daily":
                        // 每日提醒：无需额外处理
                        break;
                    case "weekly":
                        if (dto.getWeeklyDays() != null && !dto.getWeeklyDays().isEmpty()) {
                            reminderRule.setWeeklyDays(dto.getWeeklyDays());
                        }
                        break;
                    case "monthly":
                        if (dto.getMonthlyDays() != null && !dto.getMonthlyDays().isEmpty()) {
                            reminderRule.setMonthlyDays(dto.getMonthlyDays());
                        }
                        break;
                    case "yearly":
                        if (dto.getYearlyMonths() != null && !dto.getYearlyMonths().isEmpty()) {
                            reminderRule.setYearlyMonths(dto.getYearlyMonths());
                        }
                        if (dto.getYearlyDays() != null && !dto.getYearlyDays().isEmpty()) {
                            reminderRule.setYearlyDays(dto.getYearlyDays());
                        }
                        break;
                    case "custom":
                        if (dto.getCustomRule() != null && !dto.getCustomRule().isEmpty()) {
                            reminderRule.setCustomRule(dto.getCustomRule());
                        }
                        break;
                }

                // 计算下次提醒时间
                Date nextTrigger = calculateNextTrigger(reminderRule);
                reminderRule.setNextTrigger(nextTrigger);
                reminderRule.setUpdatedAt(new Date());

                reminderRulesService.updateReminderRules(reminderRule);
            }

            return AjaxResult.success("任务更新成功");

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("更新任务失败：" + e.getMessage());
        }
    }

    /**
     * 计算下次提醒时间
     */
    private Date calculateNextTrigger(ReminderRules reminderRule) {
        Calendar now = Calendar.getInstance();
        Calendar next = Calendar.getInstance();

        // 设置时间
        Calendar timeCalendar = Calendar.getInstance();
        timeCalendar.setTime(reminderRule.getTimeOfDay());
        next.set(Calendar.HOUR_OF_DAY, timeCalendar.get(Calendar.HOUR_OF_DAY));
        next.set(Calendar.MINUTE, timeCalendar.get(Calendar.MINUTE));
        next.set(Calendar.SECOND, 0);
        next.set(Calendar.MILLISECOND, 0);

        String frequency = reminderRule.getFrequency();

        switch (frequency) {
            case "immediate":
                // 立即推送：设为当前时间
                next = Calendar.getInstance();
                break;
            case "once":
                // 一次性推送：直接使用指定的时间
                if (reminderRule.getTimeOfDay() != null) {
                    next.setTime(reminderRule.getTimeOfDay());
                }
                break;
            case "daily":
                // 每日提醒：如果今天的时间已过，设为明天
                if (next.before(now)) {
                    next.add(Calendar.DAY_OF_YEAR, 1);
                }
                break;
            case "weekly":
                if (reminderRule.getWeeklyDays() != null) {
                    // 解析周几，格式如"[1,3,5]"或"[4]"
                    String weeklyDays = reminderRule.getWeeklyDays();
                    String[] days = weeklyDays.replaceAll("[\\[\\]]", "").split(",");

                    int nearestDay = findNearestWeekDay(now, Integer.parseInt(days[0].trim()));
                    for (String dayStr : days) {
                        int dayOfWeek = Integer.parseInt(dayStr.trim());
                        int candidateDay = findNearestWeekDay(now, dayOfWeek);
                        if (candidateDay < nearestDay) {
                            nearestDay = candidateDay;
                        }
                    }

                    next.add(Calendar.DAY_OF_YEAR, nearestDay);
                }
                break;
            case "monthly":
                if (reminderRule.getMonthlyDays() != null) {
                    // 解析每月的哪几天，格式如"[1,15]"
                    String monthlyDays = reminderRule.getMonthlyDays();
                    String[] days = monthlyDays.replaceAll("[\\[\\]]", "").split(",");

                    int currentDay = now.get(Calendar.DAY_OF_MONTH);
                    boolean foundThisMonth = false;

                    for (String dayStr : days) {
                        int targetDay = Integer.parseInt(dayStr.trim());
                        if (targetDay > currentDay || (targetDay == currentDay && next.after(now))) {
                            next.set(Calendar.DAY_OF_MONTH, targetDay);
                            foundThisMonth = true;
                            break;
                        }
                    }

                    if (!foundThisMonth) {
                        // 下个月的第一个日期
                        next.add(Calendar.MONTH, 1);
                        int firstDay = Integer.parseInt(days[0].trim());
                        next.set(Calendar.DAY_OF_MONTH, firstDay);
                    }
                }
                break;
            case "yearly":
                // yearly类型的计算相对复杂，这里简化处理
                if (reminderRule.getYearlyMonths() != null && reminderRule.getYearlyDays() != null) {
                    // 设为下一年的同一时间（简化实现）
                    next.add(Calendar.YEAR, 1);
                }
                break;
            case "custom":
                // 自定义规则（cron表达式），这里需要专门的cron解析库
                // 暂时设为明天同一时间
                next.add(Calendar.DAY_OF_YEAR, 1);
                break;
            default:
                // 默认设为明天同一时间
                next.add(Calendar.DAY_OF_YEAR, 1);
                break;
        }

        return next.getTime();
    }

    /**
     * 找到最近的指定星期几距离今天的天数
     */
    private int findNearestWeekDay(Calendar now, int targetDayOfWeek) {
        Calendar temp = Calendar.getInstance();
        temp.setTime(now.getTime());

        int currentDayOfWeek = temp.get(Calendar.DAY_OF_WEEK);
        int daysToAdd = targetDayOfWeek - currentDayOfWeek;

        if (daysToAdd < 0) {
            daysToAdd += 7; // 下周
        } else if (daysToAdd == 0) {
            // 今天是目标日，检查时间是否已过
            Calendar timeCheck = Calendar.getInstance();
            timeCheck.setTime(now.getTime());
            timeCheck.set(Calendar.HOUR_OF_DAY, temp.get(Calendar.HOUR_OF_DAY));
            timeCheck.set(Calendar.MINUTE, temp.get(Calendar.MINUTE));

            if (timeCheck.before(now)) {
                daysToAdd = 7; // 下周
            }
        }

        return daysToAdd;
    }

    /**
     * 获取用户的任务列表（当前周期未完成的任务）
     */
    @PostMapping("/getUserTasks")
    @ResponseBody
    public AjaxResult getUserTasks() {
        try {
            // 获取当前登录用户ID
            Long userId = SecurityUtils.getUserId();

            // 查询用户作为接收人的任务列表
            TaskRecipients searchCriteria = new TaskRecipients();
            searchCriteria.setUserId(userId);
            List<TaskRecipients> taskRecipients = taskRecipientsService.selectTaskRecipientsList(searchCriteria);

            if (taskRecipients == null || taskRecipients.isEmpty()) {
                return AjaxResult.success("暂无任务", new ArrayList<>());
            }

            // 构建返回数据
            List<Tydto> userTasks = new ArrayList<>();
            for (TaskRecipients taskRecipient : taskRecipients) {
                Tasks task = tasksService.selectTasksById(taskRecipient.getTaskId());
                if (task != null && task.getIsActive() != null && task.getIsActive() == 1) {
                    // 查询该任务的当前周期
                    LambdaQueryWrapper<TaskCycleDeadlines> cycleQuery = new LambdaQueryWrapper<>();
                    cycleQuery.eq(TaskCycleDeadlines::getTaskId, task.getId())
                            .eq(TaskCycleDeadlines::getIsCurrent, 1)
                            .ge(TaskCycleDeadlines::getDeadline, new Date());
                    TaskCycleDeadlines currentCycle = taskCycleDeadlinesMapper.selectOne(cycleQuery);

                    if (currentCycle != null) {
                        // 查询用户在该周期的完成状态
                        LambdaQueryWrapper<UserTaskCompletion> completionQuery = new LambdaQueryWrapper<>();
                        completionQuery.eq(UserTaskCompletion::getTaskId, task.getId())
                                .eq(UserTaskCompletion::getUserId, userId)
                                .eq(UserTaskCompletion::getCycleId, currentCycle.getId());
                        UserTaskCompletion userCompletion = userTaskCompletionService.selectOne(completionQuery);

                        // 只返回未完成的任务（进行中或已逾期）
                        if ("进行中".equals(userCompletion.getStatus()) && isTaskValid(task)) {

                            Tydto userTask = Tydto.fromTasks(task);

                            // 获取提醒规则
                            ReminderRules reminderRule = reminderRulesService.selectReminderRulesByTaskId(task.getId());
                            if (reminderRule != null) {
                                userTask.setFrequency(reminderRule.getFrequency());
                                if (reminderRule.getTimeOfDay() != null) {
                                    SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                                    userTask.setTimeOfDay(timeFormat.format(reminderRule.getTimeOfDay()));
                                }
                                userTask.setWeeklyDays(reminderRule.getWeeklyDays());
                                userTask.setMonthlyDays(reminderRule.getMonthlyDays());
                                userTask.setYearlyMonths(reminderRule.getYearlyMonths());
                                userTask.setYearlyDays(reminderRule.getYearlyDays());
                                userTask.setCustomRule(reminderRule.getCustomRule());
                            }

                            // 使用转换方法添加周期信息
                            Tydto cycleDto = Tydto.fromTaskCycleDeadlines(currentCycle);
                            // 复制周期相关字段到userTask
                            copyCycleFields(cycleDto, userTask);

                            // 格式化周期截止时间为字符串（保持向后兼容）
                            if (currentCycle.getDeadline() != null) {
                                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                                userTask.setCycleDeadline(dateFormat.format(currentCycle.getDeadline()));
                            }

                            // 添加用户完成状态
                            if (userCompletion != null) {
                                Tydto completionDto = Tydto.fromUserTaskCompletion(userCompletion);
                                // 复制用户完成状态相关字段到userTask
                                copyCompletionFields(completionDto, userTask);
                            }

                            userTasks.add(userTask);
                        }
                    }
                }
            }
            return AjaxResult.success("查询成功", userTasks);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("查询用户任务失败：" + e.getMessage());
        }
    }

    @PostMapping("/getUserTasksGroupedByFrequency")
    @ResponseBody
    public AjaxResult getUserTasksGroupedByFrequency() {
        try {
            Long userId = SecurityUtils.getUserId();
            TaskRecipients searchCriteria = new TaskRecipients();
            searchCriteria.setUserId(userId);
            List<TaskRecipients> taskRecipients = taskRecipientsService.selectTaskRecipientsList(searchCriteria);

            if (taskRecipients == null || taskRecipients.isEmpty()) {
                return AjaxResult.success("暂无任务", new ArrayList<>());
            }

            List<Tydto> userTasks = new ArrayList<>();

            for (TaskRecipients taskRecipient : taskRecipients) {
                Tasks task = tasksService.selectTasksById(taskRecipient.getTaskId());
                if (!isTaskValid(task))
                    continue;

                // 查询当前周期
                LambdaQueryWrapper<TaskCycleDeadlines> cycleQuery = new LambdaQueryWrapper<>();
                cycleQuery.eq(TaskCycleDeadlines::getTaskId, task.getId())
                        .eq(TaskCycleDeadlines::getIsCurrent, 1);
                TaskCycleDeadlines currentCycle = taskCycleDeadlinesMapper.selectOne(cycleQuery);
                System.out.println(currentCycle);

                // 查询用户完成状态
                LambdaQueryWrapper<UserTaskCompletion> completionQuery = new LambdaQueryWrapper<>();
                completionQuery.eq(UserTaskCompletion::getTaskId, task.getId())
                        .eq(UserTaskCompletion::getUserId, userId)
                        .eq(UserTaskCompletion::getCycleId, currentCycle.getId());
                UserTaskCompletion userCompletion = userTaskCompletionService.selectOne(completionQuery);
                System.out.println(userCompletion);
                Tydto userTask = Tydto.fromTasks(task);

                // 提醒规则
                ReminderRules reminderRule = reminderRulesService.selectReminderRulesByTaskId(task.getId());
                if (reminderRule != null) {
                    userTask.setFrequency(reminderRule.getFrequency());
                    if (reminderRule.getTimeOfDay() != null) {
                        SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
                        userTask.setTimeOfDay(timeFormat.format(reminderRule.getTimeOfDay()));
                    }
                    userTask.setWeeklyDays(reminderRule.getWeeklyDays());
                    userTask.setMonthlyDays(reminderRule.getMonthlyDays());
                    userTask.setYearlyMonths(reminderRule.getYearlyMonths());
                    userTask.setYearlyDays(reminderRule.getYearlyDays());
                    userTask.setCustomRule(reminderRule.getCustomRule());
                }

                // 周期信息
                Tydto cycleDto = Tydto.fromTaskCycleDeadlines(currentCycle);
                copyCycleFields(cycleDto, userTask);

                // 完成状态
                Tydto completionDto = Tydto.fromUserTaskCompletion(userCompletion);
                copyCompletionFields(completionDto, userTask);
                System.out.println(userTask);
                userTasks.add(userTask);
            }

            return AjaxResult.success("查询成功", userTasks);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("查询用户任务失败：" + e.getMessage());
        }
    }

    /**
     * 获取任务详情（简化版）
     */
    @PostMapping("/getTaskDetail")
    @ResponseBody
    public AjaxResult getTaskDetail(@RequestBody Tydto taskDto) {
        try {
            Long userId = SecurityUtils.getUserId();
            if (taskDto.getTaskId() == null)
                return AjaxResult.error("任务ID不能为空");

            Tasks task = tasksService.selectTasksById(taskDto.getTaskId());
            if (task == null)
                return AjaxResult.error("任务不存在");

            Tydto taskDetail = Tydto.fromTasks(task);

            // 任务创建者
            SysUser creator = userService.selectUserById(task.getCreatorId());
            if (creator != null)
                taskDetail.setCreatorName(creator.getNickName());

            // 提醒规则
            ReminderRules reminderRule = reminderRulesService.selectReminderRulesByTaskId(task.getId());
            if (reminderRule != null) {
                taskDetail.setFrequency(reminderRule.getFrequency());
                if (reminderRule.getTimeOfDay() != null) {
                    String timeStr = ("once".equals(reminderRule.getFrequency())
                            || "immediate".equals(reminderRule.getFrequency()))
                                    ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(reminderRule.getTimeOfDay())
                                    : new SimpleDateFormat("HH:mm").format(reminderRule.getTimeOfDay());
                    taskDetail.setTimeOfDay(timeStr);
                }
                taskDetail.setWeeklyDays(reminderRule.getWeeklyDays());
                taskDetail.setMonthlyDays(reminderRule.getMonthlyDays());
                taskDetail.setYearlyMonths(reminderRule.getYearlyMonths());
                taskDetail.setYearlyDays(reminderRule.getYearlyDays());
                taskDetail.setCustomRule(reminderRule.getCustomRule());
            }

            // 当前周期
            LambdaQueryWrapper<TaskCycleDeadlines> cycleQuery = new LambdaQueryWrapper<>();
            cycleQuery.eq(TaskCycleDeadlines::getTaskId, task.getId()).eq(TaskCycleDeadlines::getIsCurrent, 1);
            TaskCycleDeadlines currentCycle = taskCycleDeadlinesMapper.selectOne(cycleQuery);
            taskDetail.fromTaskCycleDeadlines(currentCycle);
            // 所有周期
            LambdaQueryWrapper<TaskCycleDeadlines> cycleQueryAll = new LambdaQueryWrapper<>();
            cycleQueryAll.eq(TaskCycleDeadlines::getTaskId, task.getId());
            List<TaskCycleDeadlines> cycleList = taskCycleDeadlinesMapper.selectList(cycleQueryAll);
            taskDetail.setCycleAllList(cycleList);
            // 所有完成情况（包含用户信息）
            LambdaQueryWrapper<UserTaskCompletion> completionQueryAll = new LambdaQueryWrapper<>();
            completionQueryAll.eq(UserTaskCompletion::getTaskId, task.getId());
            List<UserTaskCompletion> userCompletionAllList = userTaskCompletionService.selectList(completionQueryAll);

            // 为每个完成情况添加用户信息
            List<Map<String, Object>> userCompletionWithInfoList = new ArrayList<>();
            for (UserTaskCompletion completion : userCompletionAllList) {
                // 方法1：直接将对象放入Map
                Map<String, Object> completionWithInfo = new HashMap<>();

                // 方法2：使用工具类将对象属性解构到Map中
                Map<String, Object> completionFields = ObjectToMapUtils.objectToMapByReflection(completion);
                completionWithInfo.putAll(completionFields);

                // 查询用户信息
                SysUser user = userService.selectUserById(completion.getUserId());
                if (user != null) {
                    completionWithInfo.put("userId", user.getUserId());
                    completionWithInfo.put("userName", user.getUserName());
                    completionWithInfo.put("nickName", user.getNickName());
                    completionWithInfo.put("avatar", user.getAvatar());
                    completionWithInfo.put("deptId", user.getDeptId());
                }

                userCompletionWithInfoList.add(completionWithInfo);
            }
            taskDetail.setUserCompletionAllList(userCompletionAllList);
            taskDetail.setUserCompletionWithInfoList(userCompletionWithInfoList);
            // 当前用户完成状态
            UserTaskCompletion userCompletion = null;
            if (currentCycle != null) {
                LambdaQueryWrapper<UserTaskCompletion> completionQuery = new LambdaQueryWrapper<>();
                completionQuery.eq(UserTaskCompletion::getTaskId, task.getId())
                        .eq(UserTaskCompletion::getUserId, userId)
                        .eq(UserTaskCompletion::getCycleId, currentCycle.getId());
                userCompletion = userTaskCompletionService.selectOne(completionQuery);
            }
            taskDetail.buildUserTaskCompletion(userCompletion);
            // 成员信息
            List<Map<String, Object>> membersList = buildMembersList(task, currentCycle);
            taskDetail.setMembers(membersList);

            // 完成率
            int completedCount = (int) membersList.stream().filter(m -> "已完成".equals(m.get("status"))).count();
            int totalMembers = membersList.size();
            double completionRate = totalMembers > 0 ? (double) completedCount / totalMembers * 100 : 0;
            taskDetail.setTotalRecipients(totalMembers);
            taskDetail.setCompletedRecipients(completedCount);
            taskDetail.setCompletionRate(completionRate);

            // 推送日志
            ReminderLogs logQuery = new ReminderLogs();
            logQuery.setTaskId(task.getId());
            logQuery.setUserId(userId);
            List<ReminderLogs> pushLogs = reminderLogsService.selectReminderLogsList(logQuery);
            taskDetail.setPushLogs(pushLogs);

            return AjaxResult.success("获取任务详情成功", taskDetail);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取任务详情失败：" + e.getMessage());
        }
    }

    /**
     * 构建成员信息列表
     */
    private List<Map<String, Object>> buildMembersList(Tasks task, TaskCycleDeadlines currentCycle) {
        List<Map<String, Object>> membersList = new ArrayList<>();
        TaskRecipients recipientsCriteria = new TaskRecipients();
        recipientsCriteria.setTaskId(task.getId());
        List<TaskRecipients> recipients = taskRecipientsService.selectTaskRecipientsList(recipientsCriteria);

        for (TaskRecipients recipient : recipients) {
            SysUser user = userService.selectUserById(recipient.getUserId());
            if (user == null)
                continue;
            Map<String, Object> memberInfo = new HashMap<>();
            memberInfo.put("userId", user.getUserId());
            memberInfo.put("name", user.getNickName() != null ? user.getNickName() : user.getUserName());
            memberInfo.put("role", "任务接收人");
            memberInfo.put("avatar", user.getAvatar());
            List<ReminderLogs> logs = reminderLogsMapper.selectList(
                    new LambdaQueryWrapper<ReminderLogs>()
                            .eq(ReminderLogs::getUserId, recipient.getUserId())
                            .eq(ReminderLogs::getTaskId, task.getId()));
            memberInfo.put("reminderLogs", logs);

            // 完成状态
            String status = "进行中";
            if (currentCycle != null) {
                LambdaQueryWrapper<UserTaskCompletion> completionQuery = new LambdaQueryWrapper<>();
                completionQuery.eq(UserTaskCompletion::getTaskId, task.getId())
                        .eq(UserTaskCompletion::getUserId, user.getUserId())
                        .eq(UserTaskCompletion::getCycleId, currentCycle.getId());
                UserTaskCompletion userCompletion = userTaskCompletionService.selectOne(completionQuery);
                if (userCompletion != null && "已完成".equals(userCompletion.getStatus())) {
                    status = "已完成";
                }
            }
            memberInfo.put("status", status);
            membersList.add(memberInfo);
        }
        return membersList;
    }

    /**
     * 检查任务是否在有效期内
     */
    private boolean isTaskValid(Tasks task) {
        Date now = new Date();

        // 检查任务是否激活
        if (task.getIsActive() == null || task.getIsActive() != 1) {
            return false;
        }

        // 检查生效开始时间（为空表示立即生效）
        if (task.getEffectiveStart() != null && now.before(task.getEffectiveStart())) {
            return false;
        }

        // 检查生效结束时间（为空表示永久有效）
        if (task.getEffectiveEnd() != null && now.after(task.getEffectiveEnd())) {
            return false;
        }

        return true;
    }

    /**
     * 完成任务
     */
    @PostMapping("/completeTask")
    @ResponseBody
    @Transactional
    public AjaxResult completeTask(@RequestBody Tydto taskDto) {
        try {
            // 查询用户在该周期的完成状态
            LambdaQueryWrapper<UserTaskCompletion> completionQuery = new LambdaQueryWrapper<>();
            completionQuery.eq(UserTaskCompletion::getId, taskDto.getUserTaskCompletionId());
            UserTaskCompletion userCompletion = userTaskCompletionService.selectOne(completionQuery);

            if (userCompletion == null) {
                return AjaxResult.error("未找到用户任务完成状态记录");
            }

            // 更新用户任务完成状态
            userCompletion.setStatus("已完成");
            userCompletion.setCompletedAt(new Date());
            userCompletion.setUpdatedAt(new Date());

            int result = userTaskCompletionMapper.updateById(userCompletion);
            if (result <= 0) {
                return AjaxResult.error("完成任务失败");
            }

            return AjaxResult.success("任务已完成");

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("完成任务失败：" + e.getMessage());
        }
    }

    /**
     * 获取所有可用的任务接收人
     */
    @PostMapping("/getAvailableRecipients")
    @ResponseBody
    public AjaxResult getAvailableRecipients() {
        try {
            // 获取所有正常状态的用户
            SysUser searchUser = new SysUser();
            searchUser.setStatus("0"); // 正常状态
            searchUser.setDeptId(SecurityUtils.getDeptId()); // 只查询当前部门下的用户
            List<SysUser> users = userService.selectUserList(searchUser);

            // 构建返回数据
            List<Tydto> recipients = new ArrayList<>();
            for (SysUser user : users) {
                Tydto recipient = new Tydto();
                recipient.setUserId(user.getUserId());
                recipient.setUserName(user.getUserName());
                recipient.setNickName(user.getNickName());
                recipient.setAvatar(user.getAvatar());
                recipients.add(recipient);
            }

            return AjaxResult.success("获取接收人列表成功", recipients);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取接收人列表失败：" + e.getMessage());
        }
    }

    /**
     * 查询内容列表（包含附件和联系人信息）
     */
    @PostMapping("/getContentList")
    @ResponseBody
    public AjaxResult getContentList(@RequestBody(required = false) Tydto dto) {
        try {
            Content queryParam = dto.toContent();
            // 查询内容列表
            List<Content> contentList = contentService.selectContentList(queryParam);
            List<Tydto> resultList = new ArrayList<>();

            // 构建返回数据
            for (Content content : contentList) {
                // 查询附件、联系人和栏目信息
                ContentAttachment attachmentQuery = new ContentAttachment();
                attachmentQuery.setContentId(content.getId());
                List<ContentAttachment> attachments = contentAttachmentMapper
                        .selectContentAttachmentList(attachmentQuery);

                ContentContact contactQuery = new ContentContact();
                contactQuery.setContentId(content.getId());
                List<ContentContact> contacts = contentContactMapper.selectContentContactList(contactQuery);

                ContentCategory category = contentCategoryMapper.selectContentCategoryById(content.getCategoryId());

                resultList.add(Tydto.fromContent(content, attachments, contacts, category));
            }

            return AjaxResult.success("查询成功", resultList);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("查询内容列表失败：" + e.getMessage());
        }
    }

    /**
     * 获取内容详情（包含附件和联系人信息）
     */
    @PostMapping("/getContentDetail")
    @ResponseBody
    public AjaxResult getContentDetail(@RequestBody Tydto dto) {
        try {
            if (dto.getId() == null) {
                return AjaxResult.error("内容ID不能为空");
            }

            Content content = contentService.selectContentById(dto.getId());
            if (content == null) {
                return AjaxResult.error("内容不存在");
            }

            // 查询附件、联系人和栏目信息
            ContentAttachment attachmentQuery = new ContentAttachment();
            attachmentQuery.setContentId(content.getId());
            List<ContentAttachment> attachments = contentAttachmentMapper.selectContentAttachmentList(attachmentQuery);

            ContentContact contactQuery = new ContentContact();
            contactQuery.setContentId(content.getId());
            List<ContentContact> contacts = contentContactMapper.selectContentContactList(contactQuery);

            ContentCategory category = contentCategoryMapper.selectContentCategoryById(content.getCategoryId());

            // 更新浏览量并返回结果
            content.setViewCount(content.getViewCount() + 1);
            contentService.updateContent(content);

            return AjaxResult.success("获取内容详情成功",
                    Tydto.fromContent(content, attachments, contacts, category));
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取内容详情失败：" + e.getMessage());
        }
    }

    /**
     * 添加应急预案（包含联系人和附件）
     */
    @PostMapping("/addEmergencyPlan")
    @ResponseBody
    @Transactional
    public AjaxResult addEmergencyPlan(@RequestBody Tydto dto) {
        try {
            // 创建内容对象
            Content content = new Content();
            content.setTitle(dto.getTitle());
            content.setSummary(dto.getSummary());
            content.setContent(dto.getContent());
            content.setCoverImage(dto.getCoverImage());
            content.setCategoryId(1L); // 应急预案栏目ID为1
            content.setStatus(Long.parseLong(dto.getStatus())); // 已发布状态
            content.setCreatorId(SecurityUtils.getUserId());
            content.setViewCount(0L);
            content.setPublishTime(dto.getPublishTime());
            content.setCreateTime(new Date());
            content.setUpdateTime(new Date());
            content.setCreateBy(SecurityUtils.getUsername());
            content.setUpdateBy(SecurityUtils.getUsername());

            // 保存内容
            int result = contentService.insertContent(content);
            if (result <= 0) {
                return AjaxResult.error("发布应急预案失败");
            }

            // 处理图片附件
            if (dto.getImages() != null && !dto.getImages().isEmpty()) {
                for (int i = 0; i < dto.getImages().size(); i++) {
                    String imageUrl = dto.getImages().get(i);
                    ContentAttachment attachment = new ContentAttachment();
                    attachment.setContentId(content.getId());
                    attachment.setName("图片" + (i + 1));
                    attachment.setUrl(imageUrl);
                    attachment.setFileType("jpg");
                    attachment.setSort((long) i);
                    attachment.setCreateTime(new Date());
                    contentAttachmentMapper.insertContentAttachment(attachment);
                }
            }

            // 处理文档附件
            if (dto.getAttachments() != null && !dto.getAttachments().isEmpty()) {
                for (int i = 0; i < dto.getAttachments().size(); i++) {
                    ContentAttachment attachment = dto.getAttachments().get(i);
                    attachment.setContentId(content.getId());
                    attachment.setSort((long) i);
                    attachment.setCreateTime(new Date());
                    contentAttachmentMapper.insertContentAttachment(attachment);
                }
            }

            // 处理联系人
            if (dto.getContacts() != null && !dto.getContacts().isEmpty()) {
                for (int i = 0; i < dto.getContacts().size(); i++) {
                    ContentContact contact = dto.getContacts().get(i);
                    contact.setContentId(content.getId());
                    contact.setSort((long) i);
                    contact.setCreateTime(new Date());
                    contentContactMapper.insertContentContact(contact);
                }
            }

            return AjaxResult.success("发布应急预案成功", content.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("发布应急预案失败：" + e.getMessage());
        }
    }

    /**
     * 添加内容附件
     */
    @PostMapping("/addContentAttachment")
    @ResponseBody
    public AjaxResult addContentAttachment(@RequestBody Tydto dto) {
        try {
            // 验证必填字段
            if (dto.getContentId() == null) {
                return AjaxResult.error("内容ID不能为空");
            }
            if (dto.getUrl() == null || dto.getUrl().trim().isEmpty()) {
                return AjaxResult.error("附件URL不能为空");
            }

            // 创建附件对象
            ContentAttachment attachment = new ContentAttachment();
            attachment.setContentId(dto.getContentId());
            attachment.setName(dto.getName());
            attachment.setUrl(dto.getUrl());
            attachment.setFileType(dto.getFileType());
            attachment.setFileSize(dto.getFileSize());
            attachment.setSort(dto.getSort() != null ? dto.getSort() : 0L);
            attachment.setCreateTime(new Date());

            // 保存附件
            int result = contentAttachmentMapper.insertContentAttachment(attachment);
            if (result <= 0) {
                return AjaxResult.error("添加附件失败");
            }

            return AjaxResult.success("添加附件成功", attachment.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("添加附件失败：" + e.getMessage());
        }
    }

    /**
     * 添加内容联系人
     */
    @PostMapping("/addContentContact")
    @ResponseBody
    public AjaxResult addContentContact(@RequestBody Tydto dto) {
        try {
            // 验证必填字段
            if (dto.getContentId() == null) {
                return AjaxResult.error("内容ID不能为空");
            }
            if (dto.getName() == null || dto.getName().trim().isEmpty()) {
                return AjaxResult.error("联系人姓名不能为空");
            }
            if (dto.getPhone() == null || dto.getPhone().trim().isEmpty()) {
                return AjaxResult.error("联系电话不能为空");
            }

            // 创建联系人对象
            ContentContact contact = new ContentContact();
            contact.setContentId(dto.getContentId());
            contact.setName(dto.getName());
            contact.setRole(dto.getRole());
            contact.setPhone(dto.getPhone());
            contact.setSort(dto.getSort() != null ? dto.getSort() : 0L);
            contact.setCreateTime(new Date());

            // 保存联系人
            int result = contentContactMapper.insertContentContact(contact);
            if (result <= 0) {
                return AjaxResult.error("添加联系人失败");
            }

            return AjaxResult.success("添加联系人成功", contact.getId());
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("添加联系人失败：" + e.getMessage());
        }
    }

    /**
     * 获取用户通知列表
     */
    @PostMapping("/getNotificationList")
    @ResponseBody
    public AjaxResult getNotificationList() {
        try {
            // 获取当前登录用户ID
            Long userId = SecurityUtils.getUserId();

            // 查询用户的通知列表（包括已读和未读）
            List<Tydto> notificationList = notificationService.selectUserNotificationList(userId);

            return AjaxResult.success("获取通知列表成功", notificationList);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取通知列表失败：" + e.getMessage());
        }
    }

    /**
     * 获取通知详情
     */
    @PostMapping("/getNotificationDetail")
    @ResponseBody
    public AjaxResult getNotificationDetail(@RequestBody Tydto dto) {
        try {
            // 验证参数
            if (dto.getNotificationId() == null) {
                return AjaxResult.error("通知ID不能为空");
            }

            // 获取当前登录用户ID
            Long userId = SecurityUtils.getUserId();

            // 查询通知详情
            Tydto notificationDetail = notificationService.selectNotificationDetail(dto.getNotificationId());

            if (notificationDetail == null) {
                return AjaxResult.error("通知不存在");
            }

            // 标记通知为已读
            userNotificationService.markAsRead(userId, dto.getNotificationId());

            return AjaxResult.success("获取通知详情成功", notificationDetail);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取通知详情失败：" + e.getMessage());
        }
    }

    /**
     * 标记所有通知为已读
     */
    @PostMapping("/markAllNotificationsAsRead")
    @ResponseBody
    public AjaxResult markAllNotificationsAsRead() {
        try {
            // 获取当前登录用户ID
            Long userId = SecurityUtils.getUserId();

            // 标记所有通知为已读
            int result = userNotificationService.markAllAsRead(userId);

            return AjaxResult.success("已全部标为已读", result);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("标记已读失败：" + e.getMessage());
        }
    }

    /**
     * 标记单个通知为已读
     */
    @PostMapping("/markNotificationAsRead")
    @ResponseBody
    public AjaxResult markNotificationAsRead(@RequestBody Tydto dto) {
        try {
            // 验证参数
            if (dto.getNotificationId() == null) {
                return AjaxResult.error("通知ID不能为空");
            }

            // 获取当前登录用户ID
            Long userId = SecurityUtils.getUserId();

            // 标记通知为已读
            boolean result = userNotificationService.markAsRead(userId, dto.getNotificationId());

            if (result) {
                return AjaxResult.success("标记已读成功");
            } else {
                return AjaxResult.error("标记已读失败，可能通知不存在或已经是已读状态");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("标记已读失败：" + e.getMessage());
        }
    }

    /**
     * 提交随手拍
     */
    @PostMapping("/submitSnapshot")
    @ResponseBody
    @Transactional
    public AjaxResult submitSnapshot(@RequestBody Tydto dto) {
        try {
            // 创建随手拍对象
            SysSnapshot sysSnapshot = new SysSnapshot();
            sysSnapshot.setLocation(dto.getLocation());
            sysSnapshot.setReporter(dto.getReporter());
            sysSnapshot.setContact(dto.getContact());
            sysSnapshot.setDescription(dto.getDescription());
            sysSnapshot.setStatus(0); // 初始状态：待处理
            sysSnapshot.setCreateTime(new Date());
            // 设置创建者（获取当前登录用户）
            sysSnapshot.setCreateBy(SecurityUtils.getUserId());

            // 使用 MyBatis-Plus 保存
            boolean result = sysSnapshotService.save(sysSnapshot);

            // 保存图片
            if (result && dto.getImageUrls() != null && !dto.getImageUrls().isEmpty()) {
                List<SysSnapshotImage> imageList = new ArrayList<>();
                for (String imageUrl : dto.getImageUrls()) {
                    SysSnapshotImage image = new SysSnapshotImage();
                    image.setSnapshotId(sysSnapshot.getId());
                    image.setImageUrl(imageUrl);
                    imageList.add(image);
                }
                sysSnapshotImageMapper.batchInsertSysSnapshotImage(imageList);
            }

            return result ? AjaxResult.success("提交成功", sysSnapshot.getId()) : AjaxResult.error("提交失败");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("提交随手拍失败：" + e.getMessage());
        }
    }

    /**
     * 获取随手拍历史记录
     */
    @PostMapping("/getSnapshotHistory")
    @ResponseBody
    public AjaxResult getSnapshotHistory(@RequestBody Tydto dto) {
        try {
            // 创建分页对象
            Integer pageNum = dto.getPageNum() != null ? dto.getPageNum() : 1;
            Integer pageSize = dto.getPageSize() != null ? dto.getPageSize() : 10;
            Page<SysSnapshot> page = new Page<>(pageNum, pageSize);

            // 创建查询条件
            LambdaQueryWrapper<SysSnapshot> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysSnapshot::getCreateBy, SecurityUtils.getUserId());
            queryWrapper.eq(SysSnapshot::getDelFlag, 0);
            queryWrapper.orderByDesc(SysSnapshot::getCreateTime); // 按创建时间降序排序

            // 执行分页查询
            Page<SysSnapshot> resultPage = sysSnapshotService.page(page, queryWrapper);

            // 构建返回数据
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("total", resultPage.getTotal());
            resultMap.put("rows", resultPage.getRecords());

            return AjaxResult.success("获取历史记录成功", resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取历史记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取随手拍详情
     */
    @PostMapping("/getSnapshotDetail")
    @ResponseBody
    public AjaxResult getSnapshotDetail(@RequestBody Tydto dto) {
        try {
            // 验证参数
            if (dto.getId() == null) {
                return AjaxResult.error("随手拍ID不能为空");
            }

            // 使用 MyBatis-Plus 查询基本信息
            SysSnapshot sysSnapshot = sysSnapshotService.getById(dto.getId());
            if (sysSnapshot == null) {
                return AjaxResult.error("未找到详情信息");
            }

            // 查询关联的图片
            LambdaQueryWrapper<SysSnapshotImage> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysSnapshotImage::getSnapshotId, dto.getId());
            List<SysSnapshotImage> images = sysSnapshotImageMapper.selectList(queryWrapper);
            sysSnapshot.setImages(images);

            return AjaxResult.success("获取详情成功", sysSnapshot);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取详情失败：" + e.getMessage());
        }
    }

    /**
     * 获取任务列表
     */
    @PostMapping("/getTaskList")
    @ResponseBody
    public AjaxResult getTaskList(@RequestBody(required = false) Tydto dto) {
        try {
            // 构建查询条件
            Tasks queryTask = new Tasks();
            queryTask.setDeptId(SecurityUtils.getDeptId()); // 只查询当前部门下的任务
            queryTask.setIsActive(1); // 默认只查询激活状态的任务

            // 查询任务列表
            List<Tasks> tasksList = tasksService.selectTasksList(queryTask);

            // 构建返回数据
            List<Tydto> resultList = new ArrayList<>();
            Map<String, Integer> counts = new HashMap<>();
            counts.put("all", 0);
            counts.put("进行中", 0);
            counts.put("已完结", 0);
            counts.put("未开始", 0);

            for (Tasks task : tasksList) {
                if (isTaskValid(task)) {
                    Tydto taskDto = Tydto.fromTasks(task);

                    // 获取任务接收人数量
                    TaskRecipients recipientQuery = new TaskRecipients();
                    recipientQuery.setTaskId(task.getId());
                    List<TaskRecipients> taskRecipients = taskRecipientsService
                            .selectTaskRecipientsList(recipientQuery);
                    taskDto.setTotalRecipients(taskRecipients.size());

                    // ====== 优化：根据有效期动态判断任务状态 ======
                    Date now = new Date();
                    String dynamicStatus = "进行中";
                    if (task.getEffectiveStart() != null && now.before(task.getEffectiveStart())) {
                        dynamicStatus = "未开始";
                    } else if (task.getEffectiveEnd() != null && now.after(task.getEffectiveEnd())) {
                        dynamicStatus = "已完结";
                    }
                    // 没有开始时间视为已开始，没有结束时间视为一直有效
                    // 逻辑已包含在上面判断中，无需额外处理
                    taskDto.setStatus(dynamicStatus);
                    // ====== 优化结束 ======

                    resultList.add(taskDto);

                    // 统计各状态数量
                    counts.put("all", counts.get("all") + 1);

                    // 判断任务状态（用动态状态）
                    if ("进行中".equals(dynamicStatus)) {
                        counts.put("进行中", counts.get("进行中") + 1);
                    } else if ("已完结".equals(dynamicStatus)) {
                        counts.put("已完结", counts.getOrDefault("已完结", 0) + 1);
                    } else if ("未开始".equals(dynamicStatus)) {
                        counts.put("未开始", counts.getOrDefault("未开始", 0) + 1);
                    }
                }
            }

            // 构建返回结果
            Map<String, Object> result = new HashMap<>();
            result.put("list", resultList);
            result.put("counts", counts);

            return AjaxResult.success("获取任务列表成功", result);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取任务列表失败：" + e.getMessage());
        }
    }

    /**
     * 获取任务统计数据
     */
    @PostMapping("/getTaskStatistics")
    @ResponseBody
    public AjaxResult getTaskStatistics() {
        try {
            // 获取所有激活的任务
            Tasks taskQuery = new Tasks();
            taskQuery.setIsActive(1); // 只查询激活的任务
            taskQuery.setDeptId(SecurityUtils.getDeptId()); // 只查询当前部门下的任务
            List<Tasks> allActiveTasks = tasksService.selectTasksList(taskQuery);

            // 过滤在有效期内的任务
            List<Tasks> validTasks = new ArrayList<>();
            Date currentTime = new Date();

            for (Tasks task : allActiveTasks) {
                if (isTaskValid(task)) {
                    validTasks.add(task);
                }
            }

            // 构建统计数据
            Map<String, Object> statistics = new HashMap<>();
            List<Map<String, Object>> taskDetails = new ArrayList<>();

            int totalRecipients = 0; // 总的任务联系人数
            int completedRecipients = 0; // 已完成的任务联系人数

            // 遍历每个有效任务统计其联系人完成情况
            for (Tasks task : validTasks) {
                Map<String, Object> taskDetail = new HashMap<>();
                taskDetail.put("taskId", task.getId());
                taskDetail.put("taskTitle", task.getTitle());
                taskDetail.put("taskType", task.getTaskType());
                taskDetail.put("priority", task.getPriority());
                taskDetail.put("deadline", task.getDeadline());
                taskDetail.put("status", task.getStatus());

                // 查询该任务的所有联系人
                TaskRecipients recipientQuery = new TaskRecipients();
                recipientQuery.setTaskId(task.getId());
                List<TaskRecipients> taskRecipients = taskRecipientsService.selectTaskRecipientsList(recipientQuery);

                List<Map<String, Object>> recipientDetails = new ArrayList<>();
                int taskCompletedCount = 0;

                for (TaskRecipients recipient : taskRecipients) {
                    // 获取联系人用户信息
                    SysUser user = userService.selectUserById(recipient.getUserId());
                    if (user != null) {
                        Map<String, Object> recipientDetail = new HashMap<>();
                        recipientDetail.put("userId", user.getUserId());
                        recipientDetail.put("name",
                                user.getNickName() != null ? user.getNickName() : user.getUserName());

                        // 判断该联系人是否完成了任务
                        String recipientStatus = "进行中";

                        // 查询该任务的当前周期
                        LambdaQueryWrapper<TaskCycleDeadlines> cycleQuery = new LambdaQueryWrapper<>();
                        cycleQuery.eq(TaskCycleDeadlines::getTaskId, task.getId())
                                .eq(TaskCycleDeadlines::getIsCurrent, 1);
                        TaskCycleDeadlines currentCycle = taskCycleDeadlinesMapper.selectOne(cycleQuery);

                        if (currentCycle != null) {
                            // 查询用户在该周期的完成状态
                            LambdaQueryWrapper<UserTaskCompletion> completionQuery = new LambdaQueryWrapper<>();
                            completionQuery.eq(UserTaskCompletion::getTaskId, task.getId())
                                    .eq(UserTaskCompletion::getUserId, user.getUserId())
                                    .eq(UserTaskCompletion::getCycleId, currentCycle.getId());
                            UserTaskCompletion userCompletion = userTaskCompletionService.selectOne(completionQuery);

                            if (userCompletion != null) {
                                if ("已完成".equals(userCompletion.getStatus())) {
                                    recipientStatus = "已完成";
                                } else {
                                    recipientStatus = "进行中";
                                }
                            }
                        }

                        if ("已完成".equals(recipientStatus)) {
                            taskCompletedCount++;
                            completedRecipients++;
                        }

                        recipientDetail.put("status", recipientStatus);
                        recipientDetails.add(recipientDetail);
                        totalRecipients++;
                    }
                }

                taskDetail.put("recipients", recipientDetails);
                taskDetail.put("totalRecipients", taskRecipients.size());
                taskDetail.put("completedRecipients", taskCompletedCount);
                taskDetail.put("completionRate",
                        taskRecipients.size() > 0
                                ? Math.round((double) taskCompletedCount / taskRecipients.size() * 100)
                                : 0);

                taskDetails.add(taskDetail);
            }

            // 计算总体完成率
            double overallCompletionRate = totalRecipients > 0 ? (double) completedRecipients / totalRecipients * 100
                    : 0;

            statistics.put("totalTasks", validTasks.size());
            statistics.put("totalRecipients", totalRecipients);
            statistics.put("completedRecipients", completedRecipients);
            statistics.put("pendingRecipients", totalRecipients - completedRecipients);
            statistics.put("completionRate", Math.round(overallCompletionRate));
            statistics.put("taskDetails", taskDetails);

            // 为了兼容前端现有的userDetails字段，生成一个用户维度的汇总
            Map<Long, Map<String, Object>> userSummary = new HashMap<>();
            for (Map<String, Object> taskDetail : taskDetails) {
                List<Map<String, Object>> recipients = (List<Map<String, Object>>) taskDetail.get("recipients");
                for (Map<String, Object> recipient : recipients) {
                    Long userId = (Long) recipient.get("userId");
                    String name = (String) recipient.get("name");
                    String status = (String) recipient.get("status");

                    if (!userSummary.containsKey(userId)) {
                        Map<String, Object> userInfo = new HashMap<>();
                        userInfo.put("name", name);
                        userInfo.put("totalTasks", 0);
                        userInfo.put("completedTasks", 0);
                        userSummary.put(userId, userInfo);
                    }

                    Map<String, Object> userInfo = userSummary.get(userId);
                    userInfo.put("totalTasks", (Integer) userInfo.get("totalTasks") + 1);
                    if ("已完成".equals(status)) {
                        userInfo.put("completedTasks", (Integer) userInfo.get("completedTasks") + 1);
                    }
                }
            }

            // 转换为前端需要的格式
            List<Map<String, Object>> userDetails = new ArrayList<>();
            for (Map<String, Object> userInfo : userSummary.values()) {
                int totalTasks = (Integer) userInfo.get("totalTasks");
                int completedTasks = (Integer) userInfo.get("completedTasks");

                if (totalTasks == 0) {
                    userInfo.put("status", "无任务");
                } else if (completedTasks == totalTasks) {
                    userInfo.put("status", "已完成");
                } else {
                    userInfo.put("status", "未完成");
                }

                userDetails.add(userInfo);
            }

            statistics.put("userDetails", userDetails);

            return AjaxResult.success("获取任务统计成功", statistics);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取任务统计失败：" + e.getMessage());
        }
    }

    /**
     * 删除任务接口
     */
    @PostMapping("/deleteTask")
    @ResponseBody
    @Transactional
    public AjaxResult deleteTask(@RequestBody Tydto dto) {
        try {
            if (dto.getTaskId() == null) {
                return AjaxResult.error("任务ID不能为空");
            }
            Long taskId = dto.getTaskId();
            // 1. 删除任务接收人
            taskRecipientsService.deleteTaskRecipientsByTaskId(taskId);
            // 2. 删除提醒规则
            reminderRulesService.deleteReminderRulesByTaskId(taskId);
            // 3. 删除提醒日志
            reminderLogsService.deleteReminderLogsByTaskId(taskId);
            // 4. 删除周期截止时间
            taskCycleDeadlinesMapper
                    .delete(new LambdaQueryWrapper<TaskCycleDeadlines>().eq(TaskCycleDeadlines::getTaskId, taskId));
            // 5. 删除用户任务完成状态
            userTaskCompletionMapper
                    .delete(new LambdaQueryWrapper<UserTaskCompletion>().eq(UserTaskCompletion::getTaskId, taskId));
            // 4. 删除任务本身
            int result = tasksService.deleteTasksById(taskId);
            if (result > 0) {
                return AjaxResult.success("删除任务成功");
            } else {
                return AjaxResult.error("删除任务失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("删除任务异常：" + e.getMessage());
        }
    }

    /**
     * 复制周期相关字段
     * 
     * @param source 源对象
     * @param target 目标对象
     */
    private void copyCycleFields(Tydto source, Tydto target) {
        target.setCycleId(source.getCycleId());
        target.setCycleType(source.getCycleType());
        target.setCycleStart(source.getCycleStart());
        target.setCycleEnd(source.getCycleEnd());
        target.setCycleDeadlineDate(source.getCycleDeadlineDate());
        target.setIsCurrent(source.getIsCurrent());
        target.setNextTrigger(source.getNextTrigger());
        target.setCycleCreatedAt(source.getCycleCreatedAt());
        target.setCycleUpdatedAt(source.getCycleUpdatedAt());
    }

    /**
     * 复制用户完成状态相关字段
     * 
     * @param source 源对象
     * @param target 目标对象
     */
    private void copyCompletionFields(Tydto source, Tydto target) {
        target.setCompletionStatus(source.getUserTaskCompletionStatus());
        target.setCompletedAt(source.getUserTaskCompletedAt());
        target.setUserTaskCompletionId(source.getUserTaskCompletionId());
        target.setUserTaskCompletionStatus(source.getUserTaskCompletionStatus());
        target.setUserTaskCompletedAt(source.getUserTaskCompletedAt());
        target.setUserTaskCompletionCreatedAt(source.getUserTaskCompletionCreatedAt());
        target.setUserTaskCompletionUpdatedAt(source.getUserTaskCompletionUpdatedAt());
    }

    /**
     * 将对象的所有属性解构到Map中
     * 
     * @param obj 要解构的对象
     * @return 包含对象所有属性的Map
     */
    private Map<String, Object> objectToMap(Object obj) {
        Map<String, Object> map = new HashMap<>();
        if (obj == null) {
            return map;
        }

        try {
            Class<?> clazz = obj.getClass();
            Field[] fields = clazz.getDeclaredFields();

            for (Field field : fields) {
                field.setAccessible(true);
                Object value = field.get(obj);
                map.put(field.getName(), value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return map;
    }

    /**
     * 将对象解构到Map中，同时添加额外的信息
     * 
     * @param obj            要解构的对象
     * @param additionalInfo 额外的信息Map
     * @return 包含对象属性和额外信息的Map
     */
    private Map<String, Object> objectToMapWithInfo(Object obj, Map<String, Object> additionalInfo) {
        Map<String, Object> result = objectToMap(obj);
        if (additionalInfo != null) {
            result.putAll(additionalInfo);
        }
        return result;
    }

    /**
     * 示例：展示各种对象解构到Map的方法
     */
    @PostMapping("/objectToMapExample")
    @ResponseBody
    public AjaxResult objectToMapExample(@RequestBody Tydto dto) {
        try {
            // 创建一个示例对象
            UserTaskCompletion completion = new UserTaskCompletion();
            completion.setId(1);
            completion.setTaskId(100);
            completion.setUserId(1001L);
            completion.setStatus("进行中");
            completion.setCreatedAt(new Date());

            Map<String, Object> result = new HashMap<>();

            // 方法1：直接将对象放入Map
            Map<String, Object> method1 = new HashMap<>();
            method1.put("completion", completion);
            result.put("method1_direct", method1);

            // 方法2：使用反射解构对象
            Map<String, Object> method2 = ObjectToMapUtils.objectToMapByReflection(completion);
            result.put("method2_reflection", method2);

            // 方法3：使用Jackson解构对象
            Map<String, Object> method3 = ObjectToMapUtils.objectToMapByJackson(completion);
            result.put("method3_jackson", method3);

            // 方法4：只解构指定字段
            Map<String, Object> method4 = ObjectToMapUtils.objectToMapByFields(
                    completion, "id", "taskId", "userId", "status");
            result.put("method4_selected", method4);

            // 方法5：只包含非null属性
            Map<String, Object> method5 = ObjectToMapUtils.objectToMapNonNull(completion);
            result.put("method5_nonNull", method5);

            // 方法6：使用字段名映射
            Map<String, String> fieldMapping = new HashMap<>();
            fieldMapping.put("id", "completionId");
            fieldMapping.put("taskId", "taskId");
            fieldMapping.put("userId", "userId");
            fieldMapping.put("status", "completionStatus");
            Map<String, Object> method6 = ObjectToMapUtils.objectToMapWithMapping(completion, fieldMapping);
            result.put("method6_mapped", method6);

            // 方法7：添加额外信息
            Map<String, Object> additionalInfo = new HashMap<>();
            additionalInfo.put("extraField1", "额外信息1");
            additionalInfo.put("extraField2", "额外信息2");
            Map<String, Object> method7 = ObjectToMapUtils.objectToMapWithInfo(completion, additionalInfo);
            result.put("method7_withInfo", method7);

            return AjaxResult.success("对象解构示例", result);

        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("示例执行失败：" + e.getMessage());
        }
    }

    /**
     * 获取随手拍流程列表（分页+状态筛选，MyBatis-Plus实现）
     */
    @PostMapping("/getSnapshotProcessList")
    @ResponseBody
    public AjaxResult getSnapshotProcessList(@RequestBody(required = false) Tydto dto) {
        try {
            Integer pageNum = dto != null && dto.getPageNum() != null ? dto.getPageNum() : 1;
            Integer pageSize = dto != null && dto.getPageSize() != null ? dto.getPageSize() : 10;
            Integer status = dto != null && dto.getStatus() != null ? Integer.valueOf(String.valueOf(dto.getStatus()))
                    : null;
            Page<SysSnapshot> page = new Page<>(pageNum, pageSize);
            LambdaQueryWrapper<SysSnapshot> queryWrapper = new LambdaQueryWrapper<>();
            if (status != null) {
                queryWrapper.eq(SysSnapshot::getStatus, status);
            }
            queryWrapper.orderByDesc(SysSnapshot::getCreateTime);
            Page<SysSnapshot> resultPage = sysSnapshotService.page(page, queryWrapper);
            // 组装图片
            for (SysSnapshot snapshot : resultPage.getRecords()) {
                LambdaQueryWrapper<SysSnapshotImage> imgQuery = new LambdaQueryWrapper<>();
                imgQuery.eq(SysSnapshotImage::getSnapshotId, snapshot.getId());
                List<SysSnapshotImage> images = sysSnapshotImageMapper.selectList(imgQuery);
                snapshot.setImages(images);
            }
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("total", resultPage.getTotal());
            resultMap.put("rows", resultPage.getRecords());
            return AjaxResult.success("获取流程列表成功", resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("获取流程列表失败：" + e.getMessage());
        }
    }

    /**
     * 处理随手拍流程（更新状态和处理备注，MyBatis-Plus实现）
     */
    @PostMapping("/processSnapshot")
    @ResponseBody
    public AjaxResult processSnapshot(@RequestBody Tydto dto) {
        try {
            if (dto.getId() == null) {
                return AjaxResult.error("随手拍ID不能为空");
            }
            SysSnapshot snapshot = sysSnapshotService.getById(dto.getId());
            if (snapshot == null) {
                return AjaxResult.error("未找到随手拍信息");
            }
            Integer statusInt = null;
            try {
                statusInt = Integer.valueOf(String.valueOf(dto.getStatus()));
            } catch (Exception e) {
                return AjaxResult.error("处理状态格式错误");
            }
            snapshot.setStatus(statusInt);
            snapshot.setProcessRemark(dto.getProcessRemark());
            snapshot.setProcessTime(new Date());
            snapshot.setProcessorName(SecurityUtils.getUsername());
            boolean result = sysSnapshotService.updateById(snapshot);
            return result ? AjaxResult.success("处理成功") : AjaxResult.error("处理失败");
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("处理失败：" + e.getMessage());
        }
    }

    /**
     * 创建派车申请
     */
    @PostMapping("/carApply/create")
    @ResponseBody
    public AjaxResult createCarApply(@RequestBody CarApply carApply) {
        carApply.setStatus("待审批");
        carApply.setCreateTime(new Date());
        carApply.setCreator(SecurityUtils.getUserId());
        carApply.setCreatorDept(SecurityUtils.getDeptId());
        int result = carApplyMapper.insert(carApply);
        if (result > 0) {
            return AjaxResult.success("申请成功");
        } else {
            return AjaxResult.error("申请失败");
        }
    }

    /**
     * 查询派车申请（不分页，支持管理员和普通用户）
     * 
     * @param status 状态
     * @param self   是否只查自己
     */
    @PostMapping("/carApply/list")
    @ResponseBody
    public AjaxResult listCarApply(@RequestBody(required = false) Map<String, Object> params) {
        String status = null;
        if (params != null && params.get("status") != null) {
            status = params.get("status").toString();
        }
        Long userId = SecurityUtils.getUserId();
        QueryWrapper<CarApply> wrapper = new QueryWrapper<>();
        if (status != null && !status.isEmpty()) {
            wrapper.eq("status", status);
        }
        if (SecurityUtils.hasRole("common")) {
            wrapper.eq("creator", userId);
        }
        wrapper.orderByDesc("create_time");
        List<CarApply> result = carApplyMapper.selectList(wrapper);
        return AjaxResult.success(result);
    }

    /**
     * 审核派车申请（管理员）
     */
    @PostMapping("/carApply/audit")
    @ResponseBody
    public AjaxResult auditCarApply(@RequestBody Map<String, Object> params) {
        Integer id = (Integer) params.get("id");
        String status = params.get("status").toString();
        if (!"已同意".equals(status) && !"已拒绝".equals(status)) {
            return AjaxResult.error("状态不合法");
        }
        CarApply carApply = carApplyMapper.selectById(id);
        if (carApply == null) {
            return AjaxResult.error("申请不存在");
        }
        carApply.setStatus(status);
        int result = carApplyMapper.updateById(carApply);
        if (result > 0) {
            return AjaxResult.success("审核成功");
        } else {
            return AjaxResult.error("审核失败");
        }
    }

    /**
     * 删除派车申请（管理员）
     */
    @PostMapping("/carApply/delete")
    @ResponseBody
    public AjaxResult deleteCarApply(@RequestBody Map<String, Object> params) {
        Integer id = (Integer) params.get("id");
        int result = carApplyMapper.deleteById(id);
        if (result > 0) {
            return AjaxResult.success("删除成功");
        } else {
            return AjaxResult.error("删除失败");
        }
    }

    /**
     * 删除应急预案（内容）
     */
    @PostMapping("/deleteContent")
    @ResponseBody
    @Transactional
    public AjaxResult deleteContent(@RequestBody Tydto dto) {
        try {
            if (dto.getId() == null) {
                return AjaxResult.error("内容ID不能为空");
            }
            Long contentId = dto.getId();
            // 1. 删除附件
            contentAttachmentMapper.delete(new LambdaQueryWrapper<ContentAttachment>().eq(ContentAttachment::getContentId, contentId)   );
            // 2. 删除联系人
            contentContactMapper.delete(new LambdaQueryWrapper<ContentContact>().eq(ContentContact::getContentId, contentId));
            // 3. 删除内容本身
            int result = contentService.deleteContentById(contentId);
            if (result > 0) {
                return AjaxResult.success("删除内容成功");
            } else {
                return AjaxResult.error("删除内容失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("删除内容异常：" + e.getMessage());
        }
    }
}
